@file:Suppress("unused")

package com.hjh.tool.util

import cn.hutool.core.util.ByteUtil
import cn.hutool.core.util.HexUtil
import cn.hutool.core.util.NumberUtil
import cn.hutool.core.util.PrimitiveArrayUtil
import java.nio.ByteOrder
import java.util.Locale
import kotlin.ranges.downTo
import kotlin.text.lowercase
import kotlin.text.substring
import kotlin.text.toInt

/**
 * @author： hjh
 * @createDate： 2024/11/28 16:11
 * @description：
 * @qq： 3472903821
 * @version: 1.0
 */
object MyHexUtil {

    /**
     * Byte 转 Integer
     */
    fun byteToInt(b: Byte): Int {
        return b.toInt()
    }

    /**
     * Byte 转 十六进制字符串
     */
    fun byteToHexStr(b: Byte): String {
        val temp = byteArrayOf(b)
        return HexUtil.encodeHexStr(temp)
    }

    /**
     * Byte数组 转 十六进制字符串
     */
    fun bytesToHexStr(bytes: ByteArray?): String {
        return HexUtil.encodeHexStr(bytes)
    }

    /**
     * Byte数组 转 十六进制字符串
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToHexStr(bytes: ByteArray?, start: Int, end: Int): String {
        val temp = PrimitiveArrayUtil.sub(bytes, start, end)
        return bytesToHexStr(temp)
    }

    /**
     * Byte数组 转 十六进制字符串
     *
     * @param start 开始索引（包含）
     */
    fun bytesToHexStr(bytes: ByteArray, start: Int): String {
        return bytesToHexStr(bytes, start, bytes.size)
    }

    /**
     * Byte 转 Bit
     */
    fun byteToBits(value: Byte): String {
        val bits = StringBuilder()
        for (i in 7 downTo 0) {
            bits.append((value.toInt() shr i) and 1) // 右移并与1相与，获取当前位的值
        }
        return bits.toString()
    }

    /**
     * Byte数组 转 Bit
     */
    fun bytesToBits(byteArray: ByteArray): String {
        val bits = StringBuilder()
        for (value in byteArray) {
            bits.append(byteToBits(value))
        }
        return bits.toString()
    }

    /**
     * Byte数组 转 Bit
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToBits(bytes: ByteArray?, start: Int, end: Int): String {
        val temp = PrimitiveArrayUtil.sub(bytes, start, end)
        return bytesToBits(temp)
    }

    /**
     * Byte数组 转 Bit
     *
     * @param start 开始索引（包含）
     */
    fun bytesToBits(bytes: ByteArray, start: Int): String {
        val temp = PrimitiveArrayUtil.sub(bytes, start, bytes.size)
        return bytesToBits(temp)
    }

    /**
     * 二进制转 Byte 数组
     */
    fun binaryToBytes(binaryStr: String?): ByteArray {
        if (binaryStr == null) return ByteArray(0)
        return numberToBytes(binaryToInt(binaryStr))
    }

    /**
     * 二进制 转 十六进制字符串
     */
    fun binaryToHexStr(binaryStr: String): String {
        if (!NumberUtil.isNumber(binaryStr)) return ""
        val decimal = binaryStr.toInt(2)
        val hexStr = Integer.toHexString(decimal).lowercase(Locale.getDefault())
        return if ((hexStr.length % 2 == 0)) hexStr else "0$hexStr"
    }

    /**
     * 二进制 转 十六进制字符串
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun binaryToHexStr(binaryStr: String?, start: Int, end: Int): String {
        if (binaryStr == null) return ""
        val temp = binaryStr.substring(start, end)
        return binaryToHexStr(temp)
    }

    /**
     * 二进制 转 十六进制字符串
     *
     * @param start 开始索引（包含）
     */
    fun binaryToHexStr(binaryStr: String?, start: Int): String {
        if (binaryStr == null) return ""
        return binaryToHexStr(binaryStr, start, binaryStr.length)
    }

    /**
     * 二进制 转 Integer
     */
    fun binaryToInt(binaryStr: String?): Int {
        return NumberUtil.binaryToInt(binaryStr)
    }

    /**
     * 二进制 转 Integer
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun binaryToInt(binaryStr: String, start: Int, end: Int): Int {
        return binaryToInt(binaryStr.substring(start, end))
    }

    /**
     * 二进制 转 Integer
     *
     * @param start 开始索引（包含）
     */
    fun binaryToInt(binaryStr: String, start: Int): Int {
        return binaryToInt(binaryStr, start, binaryStr.length)
    }

    /**
     * 二进制 转 Integer
     */
    fun binaryToLong(binaryStr: String?): Long {
        return NumberUtil.binaryToLong(binaryStr)
    }

    /**
     * 二进制 转 Integer
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun binaryToLong(binaryStr: String, start: Int, end: Int): Long {
        return binaryToLong(binaryStr.substring(start, end))
    }

    /**
     * 二进制 转 Integer
     *
     * @param start 开始索引（包含）
     */
    fun binaryToLong(binaryStr: String, start: Int): Long {
        return binaryToLong(binaryStr, start, binaryStr.length)
    }

    /**
     * Byte数组 转 Integer 小端
     */
    fun bytesToInt(bytes: ByteArray?): Int {
        return ByteUtil.bytesToInt(bytes)
    }

    /**
     * Byte数组 转 Integer 小端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToInt(bytes: ByteArray?, start: Int, end: Int): Int {
        return ByteUtil.bytesToInt(PrimitiveArrayUtil.sub(bytes, start, end))
    }

    /**
     * Byte数组 转 Integer 小端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToInt(bytes: ByteArray, start: Int): Int {
        return bytesToInt(bytes, start, bytes.size)
    }

    /**
     * Byte数组 转 Integer 大端
     */
    fun bytesToIntBigEndian(bytes: ByteArray): Int {
        if (bytes.size == 1) return byteToInt(bytes[0])
        return ByteUtil.bytesToInt(bytes, ByteOrder.BIG_ENDIAN)
    }

    /**
     * Byte数组 转 Integer 大端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToIntBigEndian(bytes: ByteArray?, start: Int, end: Int): Int {
        return bytesToIntBigEndian(PrimitiveArrayUtil.sub(bytes, start, end))
    }

    /**
     * Byte数组 转 Integer 大端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToIntBigEndian(bytes: ByteArray, start: Int): Int {
        return bytesToIntBigEndian(bytes, start, bytes.size)
    }

    /**
     * Byte数组 转 Long 小端
     */
    private fun bytesToLong(bytes: ByteArray): Long {
        return ByteUtil.bytesToLong(bytes)
    }

    /**
     * Byte数组 转 Long 小端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToLong(bytes: ByteArray?, start: Int, end: Int): Long {
        return bytesToLong(PrimitiveArrayUtil.sub(bytes, start, end))
    }

    /**
     * Byte数组 转 Long 小端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToLong(bytes: ByteArray, start: Int): Long {
        return bytesToLong(bytes, start, bytes.size)
    }

    /**
     * Byte数组 转 Long 大端
     */
    fun bytesToLongBigEndian(bytes: ByteArray?): Long {
        return ByteUtil.bytesToLong(bytes, ByteOrder.BIG_ENDIAN)
    }

    /**
     * Byte数组 转 Long 大端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToLongBigEndian(bytes: ByteArray?, start: Int, end: Int): Long {
        return ByteUtil.bytesToLong(PrimitiveArrayUtil.sub(bytes, start, end), ByteOrder.BIG_ENDIAN)
    }

    /**
     * Byte数组 转 Long 大端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToLongBigEndian(bytes: ByteArray, start: Int): Long {
        return bytesToLongBigEndian(bytes, start, bytes.size)
    }

    /**
     * Byte数组 转 Short 小端
     */
    fun bytesToShort(bytes: ByteArray?): Short {
        return ByteUtil.bytesToShort(bytes)
    }

    /**
     * Byte数组 转 Short 小端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToShort(bytes: ByteArray?, start: Int, end: Int): Short {
        return bytesToShort(PrimitiveArrayUtil.sub(bytes, start, end))
    }

    /**
     * Byte数组 转 Short 小端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToShort(bytes: ByteArray, start: Int): Short {
        return bytesToShort(bytes, start, bytes.size)
    }

    /**
     * Byte数组 转 Short 大端
     */
    fun bytesToShortBigEndian(bytes: ByteArray?): Short {
        return ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN)
    }

    /**
     * Byte数组 转 Short 大端
     *
     * @param start 开始索引（包含）
     * @param end   结束索引（不包含）
     */
    fun bytesToShortBigEndian(bytes: ByteArray?, start: Int, end: Int): Short {
        return bytesToShortBigEndian(PrimitiveArrayUtil.sub(bytes, start, end))
    }

    /**
     * Byte数组 转 Short 大端
     *
     * @param start 开始索引（包含）
     */
    fun bytesToShortBigEndian(bytes: ByteArray, start: Int): Short {
        return bytesToShortBigEndian(bytes, start, bytes.size)
    }

    /**
     * Integer 转 Byte[]
     */
    fun numberToBytes(i: Int?): ByteArray {
        if (i == null) return ByteArray(0)
        return byteArrayOf(i.toByte())
    }

    /**
     * Integer 转 Byte[] 小端
     */
    fun intToBytes(i: Int?): ByteArray {
        if (i == null) return ByteArray(0)
        return ByteUtil.intToBytes(i)
    }

    /**
     * Integer 转 Byte[] 大端
     */
    fun intToBytesBigEndian(i: Int?): ByteArray {
        if (i == null) return ByteArray(0)
        return ByteUtil.intToBytes(i, ByteOrder.BIG_ENDIAN)
    }

    /**
     * Short 转 Byte[] 小端
     */
    fun shortToBytes(i: Short?): ByteArray {
        if (i == null) return ByteArray(0)
        return ByteUtil.shortToBytes(i)
    }

    /**
     * Short 转 Byte[] 大端
     */
    fun shortToBytesBigEndian(i: Short?): ByteArray {
        if (i == null) return ByteArray(0)
        return ByteUtil.shortToBytes(i, ByteOrder.BIG_ENDIAN)
    }
}